package com.yiduo.outpost.gateway.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yiduo.outpost.core.model.entity.Permission;
import com.yiduo.outpost.core.model.entity.PermissionMapping;
import com.yiduo.outpost.core.model.enums.PermissionMappingType;
import com.yiduo.outpost.core.model.enums.PermissionType;
import com.yiduo.outpost.gateway.mapper.PermissionMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * @author yanwen
 */
@Slf4j
@Service
public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, Permission> implements com.yiduo.outpost.gateway.service.PermissionService {

    private List<Permission> allPermissions;
    private Map<PermissionMapping, Long> includePermissionMappingMap = new ConcurrentHashMap<>(32);
    private Map<PermissionMapping, Long> excludePermissionMappingMap = new ConcurrentHashMap<>(32);

    public List<Permission> findByGroupId(Long permissionGroupId) {
        return baseMapper.findByGroupId(permissionGroupId);
    }

    /**
     * 更新所有权限
     */
    public void refreshPermissions() {
        allPermissions = list();
        log.debug("{} permission list refreshed.", this.allPermissions.size());

        Map<PermissionMapping, Long> newIncludePermissionMappingMap = new ConcurrentHashMap<>(32);
        Map<PermissionMapping, Long> newExcludePermissionMappingMap = new ConcurrentHashMap<>(32);
        allPermissions
                .parallelStream()
                .filter(p -> Objects.nonNull(p.getMapping()))
                .forEach(permission -> Arrays.stream(permission.getMapping()).forEach(permissionMapping -> {
                    if (permissionMapping.getType() == PermissionMappingType.INCLUDE) {
                        newIncludePermissionMappingMap.put(permissionMapping, permission.getId());
                    } else {
                        newExcludePermissionMappingMap.put(permissionMapping, permission.getId());
                    }
                }));

        excludePermissionMappingMap = newExcludePermissionMappingMap;
        includePermissionMappingMap = newIncludePermissionMappingMap;
    }

    public List<Permission> getAllPermissions() {
        return allPermissions;
    }

    public List<Permission> getDataPermission(Long rootPermissionId) {
        return allPermissions.parallelStream()
                .filter(p -> Objects.equals(rootPermissionId, p.getParentId()))
                .filter(p -> Objects.equals(PermissionType.PERMISSION_DATA_FIELD, p.getPermissionType()))
                .collect(Collectors.toList());
    }

    public Map<PermissionMapping, Long> getIncludePermissionMappingMap() {
        return includePermissionMappingMap;
    }

    public Map<PermissionMapping, Long> getExcludePermissionMappingMap() {
        return excludePermissionMappingMap;
    }

}
